package sli.sli2.channels;


import javax.crypto.Cipher;

import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import org.bouncycastle.util.encoders.Base64;

/**
 * Channel for AES encrypted communication
 * @author Group 8, Khassraf Roman, Mueller Robin, Zischka Stefan
 *
 */
public class AESChannel implements Channel {
	
	private TCPChannel tcpChannel;
	private Cipher aesCipher;
	

	private SecretKeySpec secretKeySpec;
	private IvParameterSpec ivParameterSpec;
	
	public AESChannel(TCPChannel tcpChannel, byte[] secretKey, byte[] ivParameter) throws Exception{
		
		this.tcpChannel = tcpChannel;
		
		byte[] secretKey2 = new byte[16];
		
		System.arraycopy(secretKey, 0, secretKey2, 0, 16);
		
		this.secretKeySpec = new SecretKeySpec(secretKey2, "AES/CTR/NoPadding");
		this.ivParameterSpec = new IvParameterSpec(ivParameter);
		
		aesCipher = Cipher.getInstance("AES/CTR/NoPadding");	
	}

	
	@Override
	public void send(byte[] message) throws Exception {
		
		System.out.println("send: " + new String(message));
		
		aesCipher.init(Cipher.ENCRYPT_MODE, secretKeySpec , ivParameterSpec);	
		byte[] encryptedMessage = aesCipher.doFinal(message);
		
		byte[] encryptedMessageBase64 = encodeBase64(encryptedMessage);
		
		tcpChannel.send(encryptedMessageBase64);
	}

	@Override
	public String receive() throws Exception {
		
		String encryptedMessageBase64 = tcpChannel.receive();
		
		byte[] encryptedMessage = decodeBase64(encryptedMessageBase64);	
		aesCipher.init(Cipher.DECRYPT_MODE, secretKeySpec , ivParameterSpec);
		
		byte[] decryptedMessage = aesCipher.doFinal(encryptedMessage);
		
		System.out.println("recv: " + new String(decryptedMessage));
		
		return new String(decryptedMessage);
	}
	
	/**
	 * Encodes a string into Base64 format
	 * @param message - the message to encode
	 * @return the encoded message
	 */
	private byte[] encodeBase64(byte[] message){
		
		byte[] base64Message = Base64.encode(message);
		
		return base64Message;	
	}
	
	/**
	 * Decodes a string from Base64 format
	 * @param base64Message - the message to decode
	 * @return the decoded message
	 */
	private byte[] decodeBase64(String base64Message){
		
		byte[] encryptedMessage = Base64.decode(base64Message);
		
		return encryptedMessage;
	}
}

